﻿#include <iostream>
#include <string>
using namespace std;
/* 对象行为型模式
1.意图
用一个中介对象来封装一系列的对象交互。中介者使各对象不需要显式地相互引用，从而使其耦合松散，而且可以独立地改变它们之间地交互。
2.适用性
在下列情况下使用中介者模式：
a.一组对象以定义良好但是复杂地方式进行通信。产生地相互依赖关系结构混乱且难以理解
b.一个对象引用其他很多对象并且直接与这些对象通信，导致难以复用该对象
c.想定制一个分布在多个类中的行为，而又不想生成太多的子类。
*/
//转发协议
enum class Message
{
	ATW_MESSAGE,	//App-->Win
	ATM_MESSAGE,	//App-->Mac
	WTM_MESSAGE,	//Win-->Mac
};
class AbstractModule;
//抽象中介者类
class AbstractMediator
{
public:
	virtual void Transmit(Message message,AbstractModule* pm) = 0;
};
class AbstractModule
{
public:
	AbstractModule(AbstractMediator* pMediator) :pMediator(pMediator) {}
	void SendMessage(Message message)
	{
		pMediator->Transmit(message, this);
	}
	virtual void AcceptMessage(Message message) = 0;
private:
	AbstractMediator* pMediator;
};
class App :public AbstractModule
{
public:
	App(AbstractMediator* pMediator) :AbstractModule(pMediator) {}
	void AcceptMessage(Message message)
	{
		switch (message)
		{
		case Message::ATW_MESSAGE:
			cout << "Win to App" << endl;
			break;
		case Message::ATM_MESSAGE:
			cout << "Mac to App" << endl;
			break;
		}
	}
};
class Win :public AbstractModule
{
public:
	Win(AbstractMediator* pMediator) :AbstractModule(pMediator) {}
	void AcceptMessage(Message message)
	{
		switch (message)
		{
		case Message::ATW_MESSAGE:
			cout << "App to Win" << endl;
			break;
		case Message::WTM_MESSAGE:
			cout << "Mac to Win" << endl;
			break;
		}
	}
};
class Mac :public AbstractModule
{
public:
	Mac(AbstractMediator* pMediator) :AbstractModule(pMediator) {}
	void AcceptMessage(Message message)
	{
		switch (message)
		{
		case Message::ATM_MESSAGE:
			cout << "App to Mac" << endl;
			break;
		case Message::WTM_MESSAGE:
			cout << "Win to Mac" << endl;
			break;
		}
	}
};
//具体中介这类
class ConcreteMediator :public AbstractMediator
{
public:
	//为中介者设定模块
	void SetModuleApp(AbstractModule* app)
	{
		this->app = app;
	}
	void SetModuleWin(AbstractModule* win)
	{
		this->win = win;
	}
	void SetModuleMac(AbstractModule* mac)
	{
		this->mac = mac;
	}
	//转发
	void Transmit(Message message, AbstractModule* pM)
	{
		switch (message)
		{
		case Message::ATM_MESSAGE:
		{
			//通过dynamic_cast转换确认指针指向的子类类型
			AbstractModule* app = dynamic_cast<AbstractModule*>(pM);
			if (app != NULL)
			{
				mac->AcceptMessage(message);
			}
			else
			{
				app->AcceptMessage(message);
			}
			break;
		}
		case Message::WTM_MESSAGE:
		{
			AbstractModule* win = dynamic_cast<AbstractModule*>(pM);
			if (win != NULL)
			{
				mac->AcceptMessage(message);
			}
			else
			{
				win->AcceptMessage(message);
			}
			break;
		}
		case Message::ATW_MESSAGE:
		{
			AbstractModule* app = dynamic_cast<AbstractModule*>(pM);
			if ( app!= NULL)
			{
				win->AcceptMessage(message);
			}
			else
			{
				app->AcceptMessage(message);
			}
			break;
		}
		}
	}
protected:
	AbstractModule* app = nullptr;
	AbstractModule* win = nullptr;
	AbstractModule* mac = nullptr;
};
/*
int main()
{
	AbstractMediator* pMediator = new ConcreteMediator;
	//指定中介者
	AbstractModule* app = new App(pMediator);
	AbstractModule* win = new Win(pMediator);
	AbstractModule* mac = new Mac(pMediator);

	//为中介者设定模块
	ConcreteMediator* pC = dynamic_cast<ConcreteMediator*>(pMediator);
	pC->SetModuleApp(app);
	pC->SetModuleWin(win);
	pC->SetModuleMac(mac);

	//不同模块间进行通信
	app->SendMessage(Message::ATM_MESSAGE);
	app->SendMessage(Message::ATW_MESSAGE);
	win->SendMessage(Message::WTM_MESSAGE);
	mac->SendMessage(Message::WTM_MESSAGE);
	mac->SendMessage(Message::ATM_MESSAGE);
	return 0;
}
*/